#include "stdafx.h"

#include "type.h"
#include "../inc/page.h"
#include "../inc/PageManager.h"
#include "../inc/PageWorldSection.h"
#include "../inc/PageContentCollection.h"
#include "../inc/PageCamera.h"

using namespace PageSystem;


const uint16 Page::WORKQUEUE_PREPARE_REQUEST = 100;
const uint16 Page::WORKQUEUE_CHANGECOLLECTION_REQUEST = 101;


Page::Page(PageID pageID, PagedWorldSection* parent)
	:mID(pageID) , mParent(parent), mDeferredProcessInProgress(true), mModified(true), mWorkQueueChannel(1)
{
	assert( parent != NULL );
}

Page::~Page()
{
}

PageManager* Page::getManager() const
{
	return mParent->getManager();
}

SceneManager* Page::getSceneManager() const
{
	return mParent->getSceneManager();
}

/// 'Touch' the page to let it know it's being used
void Page::touch()
{
}

/** Load this page. 
@param synchronous Whether to force this to happen synchronously.
*/
void Page::load(bool synchronous)
{
}
/** Unload this page. 
*/
void Page::unload()
{
}

/** Returns whether this page was 'held' in the last frame, that is
was it either directly needed, or requested to stay in memory (held - as
in a buffer region for example). If not, this page is eligible for 
removal.
*/
bool Page::isHeld() const
{
	return false;
}

/// Save page data to an automatically generated file name
void Page::save()
{
}

/// Save page data to a file
void Page::save(const String& filename)
{
}
/// Save page data to a serialiser 
void Page::save(StreamSerialiser& stream)
{
}

/// Called when the frame starts
void Page::frameStart(Real timeSinceLastFrame)
{
}
/// Called when the frame ends
void Page::frameEnd(Real timeElapsed)
{
}
/// Notify a section of the current PageCamera
void Page::notifyPageCamera(PageCamera* cam)
{
}

/** Create a new PageContentCollection within this page.
This is equivalent to calling PageManager::createContentCollection and 
then attachContentCollection.
@param typeName The name of the type of content collection (see PageManager::getContentCollectionFactories)
*/
PageContentCollection* Page::createContentCollection(const String& typeName)
{
	PageManager* pPageManager = mParent->getManager();
	PageContentCollection* pNewCollection = pPageManager->createContentCollection( typeName );
	mContentCollections.push_back( pNewCollection );
	return pNewCollection;
}
/** Destroy a PageContentCollection within this page.
This is equivalent to calling detachContentCollection and 
PageManager::destroyContentCollection.
*/
void Page::destroyContentCollection(PageContentCollection* coll)
{
	ContentCollectionList::iterator pos = std::find_if( mContentCollections.begin() , mContentCollections.end() , std::bind2nd( std::equal_to<PageContentCollection*>() , coll ) );
	if( pos == mContentCollections.end() )
		return;
	mContentCollections.erase( pos );

	PageManager* pPageManager = mParent->getManager();
	pPageManager->destroyContentCollection( coll );
}
/** Destroy all PageContentCollections within this page.
*/
void Page::destroyAllContentCollections()
{
	mContentCollections.clear();
}
/// Get the number of content collections
size_t Page::getContentCollectionCount() const
{
	return mContentCollections.size();
}
/// Get a content collection
PageContentCollection* Page::getContentCollection(size_t index)
{
	assert( index < mContentCollections.size() );
	return mContentCollections[index];
}
/// Get the list of content collections
const Page::ContentCollectionList& Page::getContentCollectionList() const
{
	return mContentCollections;
}

/// WorkQueue::RequestHandler override
bool Page::canHandleRequest(const Common::WorkQueue::Request* req, const Common::WorkQueue* srcQ)
{
	if( req == NULL || srcQ == NULL )
		return false;

	if( req->getType() != WORKQUEUE_PREPARE_REQUEST && req->getType() != WORKQUEUE_CHANGECOLLECTION_REQUEST )
		return false;
	 
	const PageRequest* pPageRequest = Common::any_cast< PageRequest >( &req->getData() );
	if( pPageRequest == NULL )
		return false;

	if( pPageRequest->srcPage != this )
		return false;

	return true;
}
Common::WorkQueue::Response* Page::handleRequest(const Common::WorkQueue::Request* req, const Common::WorkQueue* srcQ)
{
	const PageRequest* pPageRequest = Common::any_cast< PageRequest >( &req->getData() );
	assert( pPageRequest != NULL );
	//asyn loading the page
}

bool Page::canHandleResponse(const Common::WorkQueue::Response* res, const Common::WorkQueue* srcQ)
{
	if( res == NULL || srcQ == NULL )
		return false;

	if( res->getRequest()->getType() != WORKQUEUE_PREPARE_REQUEST && res->getRequest()->getType() != WORKQUEUE_CHANGECOLLECTION_REQUEST )
		return false;
	 
	const PageRequest* pPageRequest = Common::any_cast< PageRequest >( &res->getRequest()->getData() );
	if( pPageRequest == NULL )
		return false;

	if( pPageRequest->srcPage != this )
		return false;

	return true;
}

void Page::handleResponse(const Common::WorkQueue::Response* res, const Common::WorkQueue* srcQ)
{
}


/** Function for writing to a stream.
*/
std::ostream& operator <<( std::ostream& o, const Page& p )
{
	return o;
}